﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpModifyElementsBehavior.h"
#include "IUiView.h"
#include "IUiDocument.h"
#include "IDocument.h"
#include "IElement.h"
#include "IElementBasicInformation.h"
#include "GbmpMoveUtils.h"
#include "GbmpUiPlatformCommandIds.h"
#include "GcmpCommandNames.h"

#include "ContainerUtil.h"
#include "IPickCandidates.h"
#include "IPick.h"
#include "ICustomizeShortcutMenuManager.h"
#include "IMenuItemContainerDefinition.h"
#include "IMenuItemDefinition.h"
#include "IGraphicsNodeReference.h"
#include "IInstance.h"
#include "ICommandMenuItemDefinition.h"
#include "IElementPosition.h"

#include "ICommandManager.h"
#include "ICommandBehavior.h"
#include "CommandParameters.h"
#include "IMainWindow.h"
#include "ISelection.h"
#include "IRibbon.h"
#include "IRibbonPage.h"

#include "GbmpControlIds.h"

#include "ICommandInteractionEventArgs.h"
#include "IInteractionEventManager.h"

#include "GnufMainWindow.h"

#include "IModelView.h"
#include "IDrawingTable.h"
#include "IGenericElement.h"

#include "IElementShapeHandle.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include <bitset>

//公共组件
#ifdef UiAdapter_IMPL
#include "UiAdapter.h"
#include "GDFoundation/ElementSetsUtils.h"
#endif

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace gcmp;


namespace
{
    // Ribbon激活器
    class RibbonActivationHelper
    {
    public:
        static RibbonActivationHelper* Get()
        {
            static RibbonActivationHelper theInstance;
            return &theInstance;
        }
        ~RibbonActivationHelper() {}

        // 记录上一个激活的page
        bool SetPreviousActivedPage(const IRibbonPage* pPage)
        {
            if (pPage)
            {
                m_previousActivedPageName = pPage->GetPageId();
            }
            else
            {
                m_previousActivedPageName = L"";
            }
            return true;
        }

        // 记录上一个激活的page，并激活指定的page
        bool ActivePageAndSetPrevious(const std::wstring& pageName)
        {
            IMainWindow* pMainWnd = IMainWindow::GetMainWindow();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pMainWnd, L"pMainWnd为空",L"GDMPLab",L"2024-03-30");
            IRibbon* pRibbon = pMainWnd->GetRibbon();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pRibbon, L"pRibbon为空",L"GDMPLab",L"2024-03-30");
            IRibbonPage* pLastActivedPage = pRibbon->GetActivatedPage();
            this->SetPreviousActivedPage(pLastActivedPage);

            if (!pRibbon->GetPage(pageName))
            {
                return false;
            }

            return pRibbon->ActivatePage(pageName);
        }

        // 激活上一个激活的page
        bool ActivePreviousPage()
        {
            IMainWindow* pMainWnd = IMainWindow::GetMainWindow();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pMainWnd, L"pMainWnd为空",L"GDMPLab",L"2024-03-30");
            IRibbon* pRibbon = pMainWnd->GetRibbon();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pRibbon, L"pRibbon为空",L"GDMPLab",L"2024-03-30");

            if (!pRibbon->GetPage(m_previousActivedPageName))
            {
                return false;
            }
            return pRibbon->ActivatePage(m_previousActivedPageName);
        }

    private:
        RibbonActivationHelper() : m_previousActivedPageName(L"") {}

    private:
        std::wstring m_previousActivedPageName;
    };
}


IElement* GbmpModifyElementsBehavior::CreateElementShadow(IUiView* pCurrentView, const ElementId& modifiedElementId)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IElement* pModifyElement = pDoc->GetElement(modifiedElementId);
    if (!pModifyElement)
        return nullptr;

    return nullptr;
}

bool GbmpModifyElementsBehavior::ModifyElement(const IUiView* pCurrentView, const ElementId& modifiedElementId, const gcmp::Vector3d& originPt, const gcmp::Vector3d& moveVector)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    const IDocument* pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IElement* pModifyElement = pDoc->GetElement(modifiedElementId);
    if (!pModifyElement)
        return false;
#ifdef UiAdapter_IMPL
    //当选中的是集合时禁止移动
    std::vector<gcmp::ElementId> elementIds{ modifiedElementId };
    std::vector<gcmp::ElementId> lstElementSetsBySelect = gdmp::ElementSetsUtils().GetRelationElementSets(pDoc, elementIds);
    if (!lstElementSetsBySelect.empty())
    {
        return false;
    }
#endif

    if (pModifyElement->GetBasicInformation()->GetIsTransient())
        return false;

    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    GbmpMoveUtils::MoveElement(pModifyElement, originPt, moveVector, pModelView);

    return true;
}

bool GbmpModifyElementsBehavior::ModifyGripPoint(IUiView* pCurrentView, const ElementId& modifiedElementId, const gcmp::Vector3d& originPt, const gcmp::Vector3d& moveVector)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IElement* pModifyElement = pDoc->GetElement(modifiedElementId);
    if (!pModifyElement)
        return false;

    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    GbmpMoveUtils::MoveElement(pModifyElement, originPt, moveVector, pModelView);

    return true;
}


OwnerPtr<IMenuItemContainerDefinition> GbmpModifyElementsBehavior::PrepareContextMenu(gcmp::IUiView* pCurrentView)
{
    DBG_WARN_AND_RETURN_UNLESS(pCurrentView != nullptr, nullptr, L"pCurrentView指针无效",L"GDMPLab",L"2024-03-30");
    IDocument *pDoc = pCurrentView->GetUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    const gcmp::GraphicsNodeReferenceOwnerPtrVector& pickCandidate = IPickCandidates::Get()->GetCurrentPick()->GetAllGraphicsNodeReferences();

    const std::wstring modifyActionMenuId = L"_ModifyActionMenu";
    OwnerPtr<IMenuItemContainerDefinition> pMenuItemContainer = IMenuItemContainerDefinition::Create(modifyActionMenuId, L"");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pMenuItemContainer, L"pMenuItemContainer为空",L"GDMPLab",L"2024-03-30");

    auto AddSubMenuFun = [&pMenuItemContainer](std::vector<OwnerPtr<IMenuItemDefinition>>& menus) {
        for (auto& iter : menus)
        {
            if (iter->GetType() == ControlDefinitionType::Separator) {
                pMenuItemContainer->AddSeparator();
            }
            else {
                pMenuItemContainer->AddSubMenuItem(TransferOwnership(iter));
            }
        }
    };

    std::vector<const IMenuItemDefinition*> menuItems;
    ICustomizeShortcutMenuManager::Get()->ReadCustomizeShortcutMenu(L"shortcutMenu_config");
    if (1 == pickCandidate.size())
    {
        IElement* pElement = pDoc->GetElement(pickCandidate.at(0)->GetElementId());
        std::vector<OwnerPtr<IMenuItemDefinition>> menus = ICustomizeShortcutMenuManager::Get()->GetShortcutMenuData(pElement);
        AddSubMenuFun(menus);

#ifdef UiAdapter_IMPL
        Sample::UiAdapter::ApplyContextMenuStrategy(pDoc, pickCandidate.at(0)->GetElementId(), pMenuItemContainer.get());
#endif
        /// TODO:后续多段线测试Element移除，需要将这里删除
        if (const IElementShapeHandle* pShapeHandle = quick_cast<IElementShapeHandle>(pElement))
        {
            IGenericElement* pGenericElement = quick_cast<IGenericElement>(pDoc->GetElement(pShapeHandle->GetMasterId()));
            if (pGenericElement)
            {
                static const Guid polylineGUID = { 0x66f65b18, 0x5408, 0x4437, { 0x86, 0x7a, 0x26, 0x48, 0xa5, 0xcc, 0xb0, 0xbe } };
                if (pGenericElement->GetExternalObject()->GetClassGuid() == polylineGUID)
                {
                    OwnerPtr<IMenuItemDefinition> pDefMenuItemAddVertex = ICommandMenuItemDefinition::Create(ID_CMD_POLYLINE_ADD_VERTEX, ID_CMD_POLYLINE_ADD_VERTEX, GBMP_TR(L"增加顶点"), L"", L"");
                    pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItemAddVertex));
                    OwnerPtr<IMenuItemDefinition> pDefMenuItemDelVertex = ICommandMenuItemDefinition::Create(ID_CMD_POLYLINE_DELETE_VERTEX, ID_CMD_POLYLINE_DELETE_VERTEX, GBMP_TR(L"删除顶点"), L"", L"");
                    pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItemDelVertex));
                }
            }
        }
        ///
        if (const IElementShapeHandle* pShapeHandle = quick_cast<IElementShapeHandle>(pElement))
        {
            IGenericElement* pGenericElement = quick_cast<IGenericElement>(pDoc->GetElement(pShapeHandle->GetMasterId()));
            if (pGenericElement)
            {
                IElementBasicInformation* pBasicInfo = pGenericElement->GetBasicInformation();
                DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pBasicInfo, L"pBasicInfo为空",L"GDMPLab",L"2024-03-30");
                if (pBasicInfo->GetCategoryUid() == BuiltInCategoryUniIdentities::BICU_DRAWING_POLYCURVE)
                {
                    OwnerPtr<IMenuItemDefinition> pDefMenuItemAddVertex = ICommandMenuItemDefinition::Create(ID_CMD_POLYLINE_ADD_VERTEX, ID_CMD_POLYLINE_ADD_VERTEX, GBMP_TR(L"增加顶点"), L"", L"");
                    OwnerPtr<IMenuItemDefinition> pDefMenuItemDelVertex = ICommandMenuItemDefinition::Create(ID_CMD_POLYLINE_DELETE_VERTEX, ID_CMD_POLYLINE_DELETE_VERTEX, GBMP_TR(L"删除顶点"), L"", L"");
                    int positionIndex = pShapeHandle->GetPositionIndexInMasterElement();
                    std::string indexString = std::bitset<sizeof(int) * 8>(positionIndex).to_string();
                    std::string auxString = indexString.substr(1,3);
                    int auxIndex = (auxString[0] - 48) * 2 + (auxString[1] - 48);
                    if (auxIndex == 0 || auxIndex == 2)
                    {
                        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItemAddVertex));
                        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItemDelVertex));
                    }
                    else if (auxIndex == 1)
                    {
                        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItemAddVertex));
                    }
                }
            }
        }
    }
    else if (ISelection::Get()->IsEmpty()) // 没有选中对象
    {
        std::vector<OwnerPtr<IMenuItemDefinition>> menus = ICustomizeShortcutMenuManager::Get()->GetShortcutMenuNoSelectData();
        AddSubMenuFun(menus);
    }
    else
    {
        // 草图编辑模式内，草图线和辅助线转换菜单项, 根据设计切换菜单出现在其他隐藏、删除菜单之前
        {
            std::vector<OwnerPtr<IMenuItemDefinition>> menus = ICustomizeShortcutMenuManager::Get()->GetDefaultShortcutMenuData();
            AddSubMenuFun(menus);
        }

        // TODO:在位编辑应该移动到GBMP配置
        if (ISelection::Get()->GetCount() == 1)
        {
            std::wstring strCmdId = ID_CMD_EDIT_INPLACE_FAMILY;

            // 当只有一个单点创建的构件被选中时， 有在位编辑这个构件的menuItem
            const std::set<OwnerPtr<IGraphicsNodeReference>, OwnerPtrContainerUtil::LessPredicate<IGraphicsNodeReference>>& selectNodes = ISelection::Get()->GetGraphicsNodeReferences();
            const IInstance* pInstance = dynamic_cast<IInstance*>(pDoc->GetElement((*selectNodes.begin())->GetElementId()));
            if (!strCmdId.empty() && pInstance)
            {
                if (pInstance->GetElementPosition() && pInstance->GetElementPosition()->GetLocalCoordinateSystems().size() == 1)
                {
                    OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"在位编辑构件"), L"", L"");
                    /*IMenuItemDefinition* pDefMenuItem = ControlDefinitionLibraryUtil::GetControlDefinition<IMenuItemDefinition>(strCmdId);
                    if (pDefMenuItem == nullptr)
                    {
                    pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"在位编辑构件"), L"", L"");
                    }*/
                    pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
                }
            }
        }

        //表格子菜单
        //如果当前鼠标邮件是表格，则添加表格的子菜单
        if (IsNeedShowTableSubMenu(pCurrentView))
        {
            AddDrawingTableMenuItem(pMenuItemContainer.get());
        }
    }

    return pMenuItemContainer;
}

bool GbmpModifyElementsBehavior::OnLButtonDoubleClick(IUiView* pCurrentView, const gcmp::Vector3d& pos, const ElementId& selectedElementId)
{
    DBG_WARN_AND_RETURN_UNLESS(pCurrentView != nullptr, nullptr, L"pCurrentView指针无效",L"GDMPLab",L"2024-03-30");
    IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_UNLESS(pUiDoc != nullptr, nullptr, L"pUiDoc指针无效",L"GDMPLab",L"2024-03-30");

    //是否默认支持双击编辑
    bool isSupportDoubleClickToEditElement = true;
    if (isSupportDoubleClickToEditElement)
    {
        IDocument* pDoc = pUiDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc指针为空",L"GDMPLab",L"2024-03-30");
        IElement* pElement = pDoc->GetElement(selectedElementId);
        if (pElement == nullptr)
            return false;

        // 老的CommandBehavior方式仍旧先保留一段时间，再统一清理掉。
        std::wstring commandName;
        if (ICommandBehavior *pCommandBehavior = pElement->GetCommandBehaviorFW())
        {
            const ICommandBehaviorData *pCommandBehaviorData =
                pCommandBehavior->GetCommandBehaviorData(ICommandBehavior::GetDoubleClickCommandType());
            if (pCommandBehaviorData)
            {
                commandName = pCommandBehaviorData->GetCommandId();
                if (!commandName.empty())
                {
                    gcmp::CommandParameters params;
                    params[L"Vector3d_X"] = pos.X();
                    params[L"Vector3d_Y"] = pos.Y();
                    params[L"Vector3d_Z"] = pos.Z();
                    const gcmp::CommandParameters dataParams = pCommandBehaviorData->GetCommandParams();
                    for (auto iter = dataParams.begin(); iter != dataParams.end(); ++iter)
                    {
                        params.insert(std::make_pair(iter->first, iter->second));
                    }
                    ICommandManager::Get()->SendCommand(commandName, params);
                    return true;
                }
            }
        }// 老方式结束。

        OwnerPtr<ICommandInteractionEventArgs> opArgs = ICommandInteractionEventArgs::Create(
            pElement);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(opArgs, L"opArgs为空",L"GDMPLab",L"2024-03-30");
        opArgs->SetClickType(ClickType::DoubleClick);
        CommandParameters cmdParams;
        cmdParams[L"Vector3d_X"] = pos.X();
        cmdParams[L"Vector3d_Y"] = pos.Y();
        cmdParams[L"Vector3d_Z"] = pos.Z();
        opArgs->SetCommandParameters(cmdParams);
        IInteractionEventManager* pMgr = IInteractionEventManager::Get();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pMgr, L"pMgr为空",L"GDMPLab",L"2024-03-30");
        pMgr->Execute(opArgs.get());
        if (opArgs->IsExcuted())
        {
            return true;
        }
    }

    return false;
}

void GbmpModifyElementsBehavior::OnSelectionChanged(IDocument* pDocument)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDocument != nullptr, L"pDocument指针无效",L"GDMPLab",L"2024-03-30");
    // 如果选择集中有对象，
    //      Ribbon在上下文页面，跳过
    //      Ribbon不在上下文页面，则激活上下文页面，并记录激活前的页面
    // 如果选择集为空，
    //      Ribbon在上下文页面，则激活之前的页面（如果有记录）
    //      Ribbon不在上下文页面，跳过

    // 如果已经在【API实验室】，则不跳到其他页面

    if (gnuf::GnufMainWindow::bnufEnabled())
    {
        // If use gnuf, do nothing
        return;
    }
    std::wstring defaultContextualPageName = ID_PAGE_GBMP_MODIFY;
    std::wstring APILabPageName = ID_PAGE_MODULE;

    IMainWindow* pMainWnd = IMainWindow::GetMainWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pMainWnd, L"pMainWnd为空",L"GDMPLab",L"2024-03-30");
    IRibbon* pRibbon = pMainWnd->GetRibbon();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRibbon, L"pRibbon为空",L"GDMPLab",L"2024-03-30");
    IRibbonPage* pCurrentActivePage = pRibbon->GetActivatedPage();
    if (pCurrentActivePage && pCurrentActivePage->GetPageId().compare(APILabPageName) == 0)
    {
        // 在API实验室页面
        RibbonActivationHelper::Get()->SetPreviousActivedPage(pCurrentActivePage);
    }
    else if (!ISelection::Get()->IsEmpty())
    {
        if (pCurrentActivePage && pCurrentActivePage->GetPageId().compare(defaultContextualPageName) == 0)
        {
            // 已经在上下文页面了
            RibbonActivationHelper::Get()->SetPreviousActivedPage(pCurrentActivePage);
        }
        else
        {
            RibbonActivationHelper::Get()->ActivePageAndSetPrevious(defaultContextualPageName);
        }
    }
    else
    {
        RibbonActivationHelper::Get()->ActivePreviousPage();
    }
}

void GbmpModifyElementsBehavior::AddDrawingTableMenuItem(IMenuItemContainerDefinition *pMenuItemContainer)
{
    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_ADD_ROW;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"添加行"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }
    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_INSERT_ROW;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"插入行"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }
    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_INSERT_ROWS;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"插入n行"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }
    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_DELETE_ROW;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"删除行"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_ADD_COLUMN;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"添加列"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_INSERT_COLUMN;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"插入列"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }
    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_INSERT_COLUMNS;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"插入n列"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_DELETE_COLUMN;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"删除列"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_BIND_RELATED_ELEMENT;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"绑定图例"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_UNBIND_RELATED_ELEMENT;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"解绑图例"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWINGTABLEMERGE_TEST;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"合并单元格"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }

    {
        std::wstring strCmdId = ID_CMD_DRAWINGTABLERESTORE_TEST;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"取消单元格合并"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }
   
    {
        std::wstring strCmdId = ID_CMD_DRAWING_TABLE_BIND_RELATED_ELEMENT_EX;
        OwnerPtr<IMenuItemDefinition> pDefMenuItem = ICommandMenuItemDefinition::Create(strCmdId, strCmdId, GBMP_TR(L"绑定图例(左下角)"), L"", L"");
        pMenuItemContainer->AddSubMenuItem(TransferOwnership(pDefMenuItem));
    }
}

bool gcmp::GbmpModifyElementsBehavior::IsNeedShowTableSubMenu(gcmp::IUiView * pCurrentView) const
{
    ElementId oEntID;
    IModelView* pModelView = pCurrentView->GetModelView();
    if (pModelView == nullptr)
        return false;

    IDocument* pDoc = pModelView->GetDocument();
    if (pDoc == nullptr)
        return false;

    Vector3d oVector;
    pCurrentView->GetCursorWorldPosition(0, oVector);
    IDrawingTable* pTableElement = nullptr;
    ISelection *pSelection = ISelection::Get();
    const GraphicsNodeReferenceOwnerPtrSet& selectedItems = pSelection->GetGraphicsNodeReferences();
    FOR_EACH(selectedItem, selectedItems)
    {
        IElement* pElement = pDoc->GetElement(selectedItem->GetElementId());
        if (pElement)
        {
            IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElement);
            if (pGenericElement)
            {
                IDrawingTable* pTableElement = quick_cast<IDrawingTable>(pGenericElement->GetExternalObject());
                if (pTableElement != nullptr)
                {
                    TableItemIndex oIndex = pTableElement->GetItemIndexByPosition(oVector);
                    if (oIndex.IsValidIndex())
                    {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

